package com.huangkailong.designpattern.proxy.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @author huangkl
 * @since 1.0.0
 */
public interface ProxyInterceptor extends InvocationHandler {
    /**
     * 获取代理的目标对象
     *
     * @return 代理目标对象.
     */
    Object getTarget();

    /**
     * 代理方法调用之前调用.
     *
     * @param proxy  代理对象
     * @param method 方法
     * @param args   方法参数
     */
    default void before(Object proxy, Method method, Object[] args) {

    }

    /**
     * 代理方法调用之后调用.
     *
     * @param proxy  代理对象
     * @param method 方法
     * @param args   方法参数
     * @param ret 方法返回值
     */
    default void after(Object proxy, Method method, Object[] args, Object ret) {

    }

    /**
     * 代理方法返回调用.
     *
     * @param proxy  代理对象
     * @param method 方法
     * @param args   方法参数
     * @param ret 方法返回值
     */
    default void afterReturning(Object proxy, Method method, Object[] args, Object ret) {

    }

    /**
     * 代理方法调抛出异常调用.
     *
     * @param proxy  代理对象
     * @param method 方法
     * @param args   方法参数
     * @param e 抛出的异常
     */
    default void throwable(Object proxy, Method method, Object[] args, Throwable e) {

    }

    @Override
    default Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object ret;
        try {
            before(proxy, method, args);
            ret = method.invoke(getTarget(), args);
            after(proxy, method, args, ret);
        } catch (Throwable e) {
            throwable(proxy, method, args, e);
            throw e;
        }
        afterReturning(proxy, method, args, ret);
        return ret;
    }
}
